package main

import (
	"fmt"
	"hello/src/code/007gin_project/web/model"
	"time"

	"github.com/dgrijalva/jwt-go"
)

/** jwt认证 */

var jwtKey = []byte("secret_key")

type Claims struct {
	UserId uint
	jwt.StandardClaims
}

// 1、生成token
func ReleaseToken(user model.User) (string, error) {
	expirationTime := time.Now().Add(7 * 24 * time.Hour)
	claims := &Claims{
		UserId: uint(user.ID),
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expirationTime.Unix(), // 设置过期时间
			IssuedAt:  time.Now().Unix(),     // token发放的时间
			Issuer:    "ocean.tech",          // token提供者
			Subject:   "user token",          // 主题
		},
	}
	// 生成token
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	tokenString, err := token.SignedString(jwtKey)
	if err != nil {
		return "", err
	}
	return tokenString, nil
}

// 2、解析token: 常用于登陆校验的中间件
func ParseToken(tokenString string) (*jwt.Token, *Claims, error) {
	chaims := &Claims{}
	token, err := jwt.ParseWithClaims(tokenString, chaims, func(token *jwt.Token) (interface{}, error) {
		return jwtKey, nil
	})
	return token, chaims, err
}

func main() {
	// 1、生成token
	var user model.User
	tokenString, _ := ReleaseToken(user)
	fmt.Println(tokenString)
	/**
	token组成三部分：协议头 + claims信息 + (前面两个+jwtKey)hash值
	1、查看协议头信息: echo eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 | base64 -D   输出: {"alg": "HS256", "typ": "JWT"}
	2、查看claims信息: echo eyJVc2VySWQiOjAsImV4cCI6MTYyOTAwNzMzNSwiaWF0IjoxNjI4NDAyNTM1LCJpc3MiOiJvY2Vhbi50ZWNoIiwic3ViIjoidXNlciB0b2tlbiJ9 | base64 -D  输出: {"UserId":0,"exp":1629007335,"iat":1628402535,"iss":"ocean.tech","sub":"user token"}%
	*/
	// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOjAsImV4cCI6MTYyOTAwNzMzNSwiaWF0IjoxNjI4NDAyNTM1LCJpc3MiOiJvY2Vhbi50ZWNoIiwic3ViIjoidXNlciB0b2tlbiJ9.Md6qfRCrKLKaPgdy1rxMWYwtxMH6cjrjJBXaynqybXg

	// 2、解析token
	token, chaims, err := ParseToken(tokenString)
	fmt.Println("token:", token)
	fmt.Println("token valid:", token.Valid)
	fmt.Println("chaims:", chaims)
	fmt.Println("err:", err)
	if err != nil || !token.Valid {
		fmt.Println("解析token失败")
	}
	userId := chaims.UserId // 验证通过后获取chaims中的userid
	fmt.Println("chaims user id:", userId)
}
